/*
 Xern Entity Relocation Network
 Copyright (C) 2011 Ronie Salgado <roniesalg@gmail.com>

 This library is free software; you can redistribute it and/or
 modify it under the terms of the GNU Lesser General Public
 License as published by the Free Software Foundation; either
 version 2.1 of the License, or (at your option) any later version.

 This library is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 Lesser General Public License for more details.

 You should have received a copy of the GNU Lesser General Public
 License along with this library; if not, write to the Free Software
 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
*/

#ifndef XERN_GEOMETRY_INSTANCE_HPP
#define XERN_GEOMETRY_INSTANCE_HPP

#include <boost/weak_ptr.hpp>
#include <boost/enable_shared_from_this.hpp>
#include <OgreRoot.h>
#include "Xern/IGeometryInstance.hpp"
#include "Xern/ISerializableResource.hpp"
#include "Xern/Json.hpp"
#include "IOgreObject.hpp"
#include "Geometry.hpp"

namespace XernOgre
{
	class GeometryInstance: public IGeometryInstance, public ISerializableResource,
		public IOgreObject, public boost::enable_shared_from_this<GeometryInstance>
	{
	public:
		GeometryInstance(boost::shared_ptr<const Geometry> geometry,
						boost::shared_ptr<OgreRenderer> renderer,
						Ogre::SceneManager *scene);
		GeometryInstance(boost::shared_ptr<OgreRenderer> renderer);
		~GeometryInstance();

		Ogre::MovableObject *GetMovable();
		Ogre::Entity *GetEntity();

		void DelayAttach(boost::shared_ptr<SceneNode> node);

		virtual ResourceFlags GetFlags() const;
		virtual void UpdateState(boost::shared_ptr<IDataFilter> stateData);

		virtual const uuid &GetId() const;
		virtual void SetId(const uuid &id);

		virtual const char *GetMimeType() const;
		virtual const char *GetFileExtension() const;

		virtual bool IsFileSerializable() const;
		virtual bool IsMemorySerializable() const;

		virtual boost::shared_ptr<IDataFilter> GetSerializedData() const;

		virtual void SetMaterial(const std::string &name);
		virtual void SetMaterial(boost::shared_ptr<IMaterial> material);

		virtual AABox GetBoundingBox() const;
		virtual void SetBoundingBox(const AABox &box);

		virtual boost::shared_ptr<Entity> GetParent() const;
		virtual void SetParent(boost::shared_ptr<Entity> parent);

		virtual void AttachToBone(const std::string &bone, boost::shared_ptr<IMovableObject> object);
		virtual void DetachFromBone(const std::string &bone, boost::shared_ptr<IMovableObject> object);

		virtual void PlayAnimation(const std::string &name, bool looped=false);
		void Frame(float delta);

		virtual void SetCustomParameter(size_t index, const SVector4 &param);

		virtual void SetTransform(const ReversibleTransform &trans);
		virtual const ReversibleTransform &GetTransform() const;

		static boost::shared_ptr<GeometryInstance>
		LoadInstance(boost::shared_ptr<OgreRenderer> renderer, const JsonObject &data);

	private:
		friend class GeometryLoadedCallback;
		typedef std::set<boost::shared_ptr<SceneNode> > DelayAttaches;

		uuid id;
		boost::shared_ptr<OgreRenderer> renderer;
		boost::shared_ptr<const Geometry> geometry;
		Ogre::SceneManager *scene;
		Ogre::Entity *entity;
		Ogre::AnimationState *currentState;
		ReversibleTransform transform;
		bool registeredAnimation;
		boost::weak_ptr<Entity> parent;
		std::set<boost::shared_ptr<IMovableObject> > attachedObjects;
		DelayAttaches delayAttaches;

		std::string delayedAnim;
		bool delayedAnimLoop;
	};
};

#endif //XERN_GEOMETRY_INSTANCE_HPP
